home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Shareware Grab Bag
/
Shareware Grab Bag.iso
/
001
/
piblist.lbr
/
FIND.PQS
/
find.pas
Wrap
Pascal/Delphi Source File
|
1985-03-28
|
13KB
|
320 lines
(*----------------------------------------------------------------------*)
(* Find_Line --- Find line on file F *)
(*----------------------------------------------------------------------*)
PROCEDURE Find_Line( n : REAL );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Find_Line *)
(* *)
(* Purpose: Finds and moves to specified line on file F *)
(* *)
(* Calling sequence: *)
(* *)
(* Find_Line( n: REAL ); *)
(* *)
(* n --- line to be found *)
(* *)
(* Calls: Read_Line *)
(* RMIN *)
(* Clear_Buffer *)
(* Skip_To_Line *)
(* Reset_F *)
(* Scan_To_Eof *)
(* *)
(* Remarks: *)
(* *)
(* On exit eod=TRUE if the line does not exist. In this case the *)
(* buffer is full and it contains the lines at end of the file. *)
(* Otherwise eod=FALSE, line n is in the buffer, and top points *)
(* to it. *)
(* *)
(* The algorithm divides into three cases. *)
(* *)
(* Case 1. The line preceeds the buffer. In this case the file *)
(* is reset and the buffer is cleared. The goal is to exit *)
(* with the buffer full and with line n at the end of the buffer. *)
(* This is accomplished by skipping the proper number of lines, *)
(* then reading lines into the buffer until line n has been *)
(* reached. *)
(* *)
(* Case 2. The line is inside the buffer. A simple linear search *)
(* of the buffer locates the requested line. *)
(* *)
(* Case 3. The line follows the buffer. This is the complicated *)
(* case. As in case 1, the goal is to exit with a full buffer *)
(* and with line n at the end of the buffer. However, if line n *)
(* does not exist then we want to exit with a full buffer *)
(* consisting of the lines at the end of the file. For efficiency *)
(* in large forward skips, we don't want to simply read lines into *)
(* the buffer until line n or eof is encountered. Skipping is *)
(* faster than reading, so we'd prefer to skip lines, then read a *)
(* full buffer's worth. The problem is to determine how many *)
(* lines to skip. *)
(* *)
(* (a) If line n is within Max_buf_lines of the last line in the *)
(* buffer then no lines are skipped. Lines are simply read *)
(* into the buffer until line n or eof is reached. This is *)
(* a "short" forwards skip. *)
(* *)
(* (b) Assume (a) doesn't hold. If n is less than or equal to the *)
(* maximum line number seen so far then we know that line n *)
(* must exist. In this case we skip to line (n-Max_buf_lines),*)
(* then read lines into the buffer until line n is reached. *)
(* *)
(* (c) Assume neither (a) nor (b) holds. If we have earlier *)
(* encountered eof on file f, then Max_line is the largest *)
(* line number on the file, and we know whether or not line *)
(* n exists. In this case we skip to line min(n,Max_line) - *)
(* Max_buf_lines, and then read lines into the buffer until *)
(* either line n or eof is reached. *)
(* *)
(* (d) If none of cases (a), (b) or (c) hold then we scan to *)
(* eof to determine whether or not line n exists. Max_line *)
(* is now the largest line number on the file. File f is *)
(* reset, and we proceed as in case (c). Note that this case *)
(* can occur at most once per run of PibList. *)
(* *)
(*----------------------------------------------------------------------*)
VAR
m: REAL;
BEGIN (* Find_Line *)
eod := FALSE;
(* Case 1 *)
IF n < First^.lnum THEN
BEGIN
Reset_F;
Clear_Buffer;
IF n > Max_buf_lines THEN Skip_To_Line( n - Max_buf_lines );
REPEAT
Read_Line;
UNTIL last^.lnum = n;
top := last
END (* Case 2 *)
ELSE IF n <= last^.lnum THEN
BEGIN
top := first;
WHILE ( Top^.lnum < n ) DO top := Top^.next
END
ELSE
BEGIN (* Case 3 *)
IF ( NOT eof_seen ) AND ( ( n - Max_buf_lines ) > last^.lnum )
AND (n > Max_line) THEN
Scan_To_Eof;
m := RMIN( n , Max_line ) - Max_buf_lines;
IF m > last^.lnum THEN
BEGIN
Clear_Buffer;
Skip_To_Line( m )
END;
REPEAT
Read_Line;
UNTIL ( last^.lnum = n ) OR EOF( F );
top := last;
eod := Top^.lnum < n;
END;
END (* Find_Line *);
(*----------------------------------------------------------------------*)
(* Find_Page --- Find first line of page on F *)
(*----------------------------------------------------------------------*)
PROCEDURE Find_Page( n : REAL );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Find_Page *)
(* *)
(* Purpose: Locates first line of page on file F. *)
(* *)
(* Calling sequence: *)
(* *)
(* Find_Page( n: REAL ); *)
(* *)
(* n --- Page to be found *)
(* *)
(* Calls: Read_Line *)
(* Skip_To_Page *)
(* Scan_To_Eof *)
(* Clear_Buffer *)
(* Reset_F *)
(* *)
(* Remarks: *)
(* *)
(* On exit eod=TRUE if the page does not exist, in which case *)
(* the buffer is full and it contains the Lines at the end of *)
(* the file. *)
(* *)
(* Otherwise eod=FALSE, the first Line of page n is in the buffer, *)
(* and top points to it. *)
(* *)
(* The algorithm used by find_page is almost identical to that used *)
(* by find_line. *)
(* *)
(*----------------------------------------------------------------------*)
VAR
before: BOOLEAN;
m: REAL;
BEGIN (* Find_Page *)
eod := FALSE;
before := ( n < First^.pnum ) OR
( ( n = First^.pnum ) AND ( First^.Txt[1] <> eject_char ) );
IF before THEN
BEGIN
Reset_F;
Clear_Buffer;
IF n > Max_buf_pages THEN Skip_To_Page ( n - Max_buf_pages );
REPEAT
Read_Line;
UNTIL last^.pnum = n;
top := last
END
ELSE IF n <= last^.pnum THEN
BEGIN
top := first;
WHILE ( Top^.pnum < n ) DO top := Top^.next
END
ELSE
BEGIN
IF ( NOT eof_seen ) AND ( ( n - Max_buf_pages ) > last^.pnum )
AND ( n > Max_page ) THEN
Scan_To_Eof;
m := RMIN( n , Max_page ) - Max_buf_pages;
IF m > last^.pnum THEN
BEGIN
Clear_Buffer;
Skip_To_Page( m )
END;
REPEAT
Read_Line;
UNTIL ( last^.pnum = n ) OR EOF( F );
top := last;
eod := Top^.pnum < n;
END;
END (* Find_Page *);
(*----------------------------------------------------------------------*)
(* Find_String --- Find next occurrence of string on F *)
(*----------------------------------------------------------------------*)
PROCEDURE Find_String( S: AnyStr );
(*----------------------------------------------------------------------*)
(* *)
(* Procedure: Find_String *)
(* *)
(* Purpose: Find next occurrence of string on F *)
(* *)
(* Calling sequence: *)
(* *)
(* Find_String( S: AnyStr ); *)
(* *)
(* S --- String to be found *)
(* *)
(* Calls: Read_Line *)
(* Find_Line *)
(* *)
(*----------------------------------------------------------------------*)
VAR
Found: BOOLEAN;
Done: BOOLEAN;
LineNo: INTEGER;
n: INTEGER;
LABEL 1;
BEGIN (* Find_String *)
Found := FALSE;
Done := FALSE;
Search_Lpos := 0;
Search_Col := 0;
REPEAT
bot := top;
LineNo := 0;
n := Height;
WHILE ( n > 0 ) AND ( NOT Eod ) DO
BEGIN
LineNo := LineNo + 1;
Search_Col := POS( Search_Str , Bot^.Txt );
IF Search_Col <> 0 THEN
BEGIN
Search_Lpos := LineNo;
Search_Line := Bot^.Lnum;
Found := TRUE;
GOTO 1;
END;
n := n - 1;
IF n > 0 THEN
IF bot = last THEN
BEGIN
Read_Line;
Eod := eof(f);
bot := last;
END
ELSE
bot := Bot^.next;
END;
Done := ( n > 0 );
IF ( NOT Done ) THEN
Find_Line( Top^.lnum + Height );
1:
UNTIL ( Found OR Done );
END (* Find_String *);